package com.bugstack.trigger.http;

import com.alibaba.fastjson.JSON;
import com.bugstack.domain.activity.model.entity.SkuProductEntity;
import com.bugstack.domain.activity.model.entity.SkuRechargeEntity;
import com.bugstack.domain.activity.model.entity.UnpaidActivityOrderEntity;
import com.bugstack.domain.activity.model.entity.UserRaffleOrderEntity;
import com.bugstack.domain.activity.model.valobj.OrderTradeTypeVO;
import com.bugstack.domain.activity.service.armory.IActivityArmory;
import com.bugstack.domain.activity.service.paytake.IActivityPayTake;
import com.bugstack.domain.activity.service.product.IRaffleActivitySkuProductService;
import com.bugstack.domain.activity.service.quota.IRaffleAccountQuotaService;
import com.bugstack.domain.award.model.entity.UserAwardRecordEntity;
import com.bugstack.domain.award.model.valobj.AwardStateVO;
import com.bugstack.domain.award.service.IAwardService;
import com.bugstack.domain.credit.model.entity.CreditAccountEntity;
import com.bugstack.domain.credit.model.entity.TradeEntity;
import com.bugstack.domain.credit.model.valobj.TradeNameVO;
import com.bugstack.domain.credit.model.valobj.TradeTypeVO;
import com.bugstack.domain.credit.service.ICreditAdjustService;
import com.bugstack.domain.rebate.model.entity.ActivityAccountEntity;
import com.bugstack.domain.rebate.model.entity.BehaviorEntity;
import com.bugstack.domain.rebate.model.valobj.BehaviorTypeVO;
import com.bugstack.domain.rebate.service.IBehaviorRebateService;
import com.bugstack.domain.strategy.model.entity.RaffleAwardEntity;
import com.bugstack.domain.strategy.model.entity.RaffleFactorEntity;
import com.bugstack.domain.strategy.service.IRaffleStrategy;
import com.bugstack.domain.strategy.service.armory.IStrategyArmory;
import com.bugstack.trigger.api.IRaffleActivityService;
import com.bugstack.trigger.api.dto.*;
import com.bugstack.types.annotations.DCCValue;
import com.bugstack.types.annotations.RateLimiterAccessInterceptor;
import com.bugstack.types.enums.ResponseCode;
import com.bugstack.types.exception.AppException;
import com.bugstack.types.model.Response;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @Author: czb
 * @Description: TODO
 * @DateTime: 2025/3/30 14:23
 **/
@RestController
@Slf4j
@CrossOrigin("${app.config.cross-origin}")
@RequestMapping("/api/${app.config.api-version}/raffle/activity/")
@DubboService(version = "1.0")
public class RaffleActivityController implements IRaffleActivityService {

    private final SimpleDateFormat dateFormatDay = new SimpleDateFormat("yyyyMMdd");

    @Resource
    private IActivityArmory activityArmory;
    @Resource
    private IStrategyArmory strategyArmory;
    @Resource
    IActivityPayTake activityPayTake;
    @Resource
    IRaffleStrategy raffleStrategy;
    @Resource
    IAwardService awardService;
    @Resource
    IBehaviorRebateService behaviorRebateService;
    @Resource
    IRaffleAccountQuotaService raffleAccountQuotaService;
    @Resource
    ICreditAdjustService creditAdjustService;
    @Resource
    IRaffleActivitySkuProductService raffleActivitySkuProductService;
    @DCCValue("degradeSwitch:close")
    private String degradeSwitch;

    @RequestMapping("armory")
    @Override
    public Response<Boolean> armory(@RequestParam Long activityId) {
        try {
            log.info("活动装配，数据预热，开始 activityId:{}", activityId);
            activityArmory.assembleActivitySkuByActivityId(activityId);
            strategyArmory.assembleLotteryStrategyByActivityId(activityId);
            Response<Boolean> response = Response.<Boolean>builder()
                    .code(ResponseCode.SUCCESS.getCode())
                    .info(ResponseCode.SUCCESS.getInfo())
                    .data(true)
                    .build();
            log.info("活动装配，数据预热，完成 activityId:{}", activityId);
            return response;
        } catch (Exception e) {
            log.error("活动装配，数据预热，失败 activityId:{}", activityId, e);
            return Response.<Boolean>builder()
                    .code(ResponseCode.UN_ERROR.getCode())
                    .info(ResponseCode.UN_ERROR.getInfo())
                    .data(false).build();
        }
    }
    /**
     * 抽奖接口
     *
     * @param request 请求对象
     * @return 抽奖结果
     * <p>
     * 接口：<a href="http://localhost:8091/api/v1/raffle/activity/draw">/api/v1/raffle/activity/draw</a>
     * 入参：{"activityId":100001,"userId":"xiaofuge"}
     * <p>
     * curl --request POST \
     * --url http://localhost:8091/api/v1/raffle/activity/draw \
     * --header 'content-type: application/json' \
     * --data '{
     * "userId":"xiaofuge",
     * "activityId": 100301
     * }'
     */
    @RequestMapping("draw")
    @RateLimiterAccessInterceptor(key = "userId", permitsPerSecond = 1.0d, blacklistCount = 1, fallbackMethod = "drawRateLimiterError")
    @HystrixCommand(commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "150")
    }, fallbackMethod = "drawHystrixError")
    @Override
    public Response<ActivityDrawResponseDTO> draw(@RequestBody ActivityDrawRequestDTO request) {
        try {
            log.info("活动抽奖开始 userId:{} activityId:{}", request.getUserId(), request.getActivityId());
            if (StringUtils.isNotBlank(degradeSwitch) && "open".equals(degradeSwitch)) {
                return Response.<ActivityDrawResponseDTO>builder()
                        .code(ResponseCode.DEGRADE_SWITCH.getCode())
                        .info(ResponseCode.DEGRADE_SWITCH.getInfo())
                        .build();
            }
            Long activityId = request.getActivityId();
            String userId = request.getUserId();
            //1.参数校验
            if (StringUtils.isBlank(userId) || null == activityId)
                return Response.<ActivityDrawResponseDTO>builder()
                        .code(ResponseCode.ILLEGAL_PARAMETER.getCode())
                        .info(ResponseCode.ILLEGAL_PARAMETER.getInfo())
                        .build();
            //2.创建抽奖订单
            UserRaffleOrderEntity orderEntity = activityPayTake.createOrder(activityId, userId);
            log.info("活动抽奖，创建订单 userId:{} activityId:{} orderId:{}", userId, activityId, orderEntity.getOrderId());
            //3.执行策略抽奖
            RaffleAwardEntity raffleAwardEntity = raffleStrategy.performRaffleStrategy(RaffleFactorEntity.builder()
                    .userId(userId)
                    .endDateTime(orderEntity.getEndDateTime())
                    .strategyId(orderEntity.getStrategyId()).build());
            //3.保存中奖结果
            awardService.saveUserAwardRecord(UserAwardRecordEntity.builder()
                    .activityId(activityId)
                    .orderId(orderEntity.getOrderId())
                    .strategyId(orderEntity.getStrategyId())
                    .awardId(raffleAwardEntity.getAwardId())
                    .awardTitle(raffleAwardEntity.getAwardTitle())
                    .awardState(AwardStateVO.create)
                    .awardTime(new Date())
                    .userId(userId)
                    .awardConfig(raffleAwardEntity.getAwardConfig())
                    .build());
            ActivityDrawResponseDTO responseDTO = new ActivityDrawResponseDTO();
            responseDTO.setAwardId(raffleAwardEntity.getAwardId());
            responseDTO.setAwardTitle(raffleAwardEntity.getAwardTitle());
            responseDTO.setAwardIndex(raffleAwardEntity.getSort());
            return Response.<ActivityDrawResponseDTO>builder()
                    .code(ResponseCode.SUCCESS.getCode())
                    .info(ResponseCode.SUCCESS.getInfo())
                    .data(responseDTO)
                    .build();

        } catch (Exception e) {
            log.error("活动抽奖失败 userId:{} activityId:{}", request.getUserId(), request.getActivityId(), e);
            return Response.<ActivityDrawResponseDTO>builder()
                    .code(ResponseCode.UN_ERROR.getCode())
                    .info(ResponseCode.UN_ERROR.getInfo())
                    .build();
        }
    }

    //限流拦截
    public Response<ActivityDrawResponseDTO> drawRateLimiterError(@RequestBody ActivityDrawRequestDTO request) {
        log.info("用户被限流拦截 userId:{} activityId:{}", request.getUserId(), request.getActivityId());
        return Response.<ActivityDrawResponseDTO>builder()
                .code(ResponseCode.RATE_LIMITER.getCode())
                .info(ResponseCode.RATE_LIMITER.getInfo())
                .build();
    }

    //熔断拦截
    public Response<ActivityDrawResponseDTO> drawHystrixError(@RequestBody ActivityDrawRequestDTO request) {
        log.info("用户被熔断拦截 userId:{} activityId:{}", request.getUserId(), request.getActivityId());
        return Response.<ActivityDrawResponseDTO>builder()
                .code(ResponseCode.HYSTRIX.getCode())
                .info(ResponseCode.HYSTRIX.getInfo())
                .build();
    }

    @RequestMapping("signRebate")
    @Override
    public Response<Boolean> signRebate(@RequestParam String userId) {
        try {
            BehaviorEntity behaviorEntity = new BehaviorEntity();
            behaviorEntity.setUserId(userId);
            behaviorEntity.setBehaviorTypeVO(BehaviorTypeVO.SIGN);
            behaviorEntity.setOutBusinessNo(dateFormatDay.format(new Date()));
            List<String> orderIds = behaviorRebateService.createOrder(behaviorEntity);
            log.info("日历签到返利完成 userId:{} orderIds: {}", userId, JSON.toJSONString(orderIds));
            return Response.<Boolean>builder()
                    .code(ResponseCode.SUCCESS.getCode())
                    .info(ResponseCode.SUCCESS.getInfo())
                    .data(true).build();
        } catch (Exception e) {
            log.error("日历签到返利失败 userId:{}", userId, e);
            return Response.<Boolean>builder()
                    .code(ResponseCode.UN_ERROR.getCode())
                    .info(ResponseCode.UN_ERROR.getInfo())
                    .data(false).build();
        }
    }

    @RequestMapping(value = "isSignRebate", method = RequestMethod.POST)
    @Override
    public Response<Boolean> isSignRebate(String userId) {
        try {
            log.info("查询今日签到开始 userId:{}", userId);
            List<BehaviorEntity> orders = behaviorRebateService.queryOrderByOutBusinessNo(userId, dateFormatDay.format(new Date()));
            log.info("查询今日签到结束 订单数量：{}", orders.size());
            return Response.<Boolean>builder()
                    .code(ResponseCode.SUCCESS.getCode())
                    .info(ResponseCode.SUCCESS.getInfo())
                    .data(!orders.isEmpty())
                    .build();
        } catch (Exception e) {
            log.error("查询今日签到失败 userId:{}", userId, e);
            return Response.<Boolean>builder()
                    .code(ResponseCode.UN_ERROR.getCode())
                    .info(ResponseCode.UN_ERROR.getInfo())
                    .data(false).build();
        }
    }

    @RequestMapping(value = "query_user_activity_account", method = RequestMethod.POST)
    @Override
    public Response<QueryAccountResponseDTO> queryUserActivityAccount(QueryAccountRequestDTO queryAccountRequestDTO) {
        String userId = queryAccountRequestDTO.getUserId();
        Long activityId = queryAccountRequestDTO.getActivityId();
        try {
            log.info("查询账户余额信息开始 userId:{} activityId:{}", userId, activityId);
            if (StringUtils.isBlank(userId) || activityId == null)
                throw new AppException(ResponseCode.ILLEGAL_PARAMETER.getCode(), ResponseCode.ILLEGAL_PARAMETER.getInfo());
            ActivityAccountEntity activityAccountEntity = behaviorRebateService.queryUserActivityAccount(userId, activityId);
            QueryAccountResponseDTO queryAccountResponseDTO = new QueryAccountResponseDTO();
            queryAccountResponseDTO.setTotalCount(activityAccountEntity.getTotalCount());
            queryAccountResponseDTO.setTotalCountSurplus(activityAccountEntity.getTotalCountSurplus());
            queryAccountResponseDTO.setMonthCount(activityAccountEntity.getMonthCount());
            queryAccountResponseDTO.setMonthCountSurplus(activityAccountEntity.getMonthCountSurplus());
            queryAccountResponseDTO.setDayCount(activityAccountEntity.getDayCount());
            queryAccountResponseDTO.setDayCountSurplus(activityAccountEntity.getDayCountSurplus());
            log.info("查询账户余额信息结束 userId:{} activityId:{} dto:{}", userId, activityId, JSON.toJSONString(queryAccountResponseDTO));
            return Response.<QueryAccountResponseDTO>builder()
                    .code(ResponseCode.SUCCESS.getCode())
                    .info(ResponseCode.SUCCESS.getInfo()).
                    data(queryAccountResponseDTO)
                    .build();
        } catch (Exception e) {
            log.error("查询账户余额失败 userId:{} activityId:{}", userId, activityId, e);
            throw new AppException(ResponseCode.UN_ERROR.getCode(), ResponseCode.UN_ERROR.getInfo());
        }
    }

    @RequestMapping(value = "query_sku_product_list", method = RequestMethod.GET)
    @Override
    public Response<List<SkuProductResponseDTO>> querySkuProductListByActivityId(Long activityId) {
        try{
            log.info("查询sku商品集合开始 activityId:{}", activityId);
            // 1. 参数校验
            if (null == activityId) {
                throw new AppException(ResponseCode.ILLEGAL_PARAMETER.getCode(), ResponseCode.ILLEGAL_PARAMETER.getInfo());
            }
            //2. 查询商品&封装数据
            List<SkuProductEntity> skuProductEntities = raffleActivitySkuProductService.querySkuProductEntityListByActivityId(activityId);
            List<SkuProductResponseDTO> skuProductResponseDTOS = new ArrayList<>(skuProductEntities.size());
            for (SkuProductEntity skuProductEntity : skuProductEntities) {

                SkuProductResponseDTO.ActivityCount activityCount = new SkuProductResponseDTO.ActivityCount();
                activityCount.setTotalCount(skuProductEntity.getActivityCount().getTotalCount());
                activityCount.setMonthCount(skuProductEntity.getActivityCount().getMonthCount());
                activityCount.setDayCount(skuProductEntity.getActivityCount().getDayCount());

                SkuProductResponseDTO skuProductResponseDTO = new SkuProductResponseDTO();
                skuProductResponseDTO.setSku(skuProductEntity.getSku());
                skuProductResponseDTO.setActivityId(skuProductEntity.getActivityId());
                skuProductResponseDTO.setActivityCountId(skuProductEntity.getActivityCountId());
                skuProductResponseDTO.setStockCount(skuProductEntity.getStockCount());
                skuProductResponseDTO.setStockCountSurplus(skuProductEntity.getStockCountSurplus());
                skuProductResponseDTO.setProductAmount(skuProductEntity.getProductAmount());
                skuProductResponseDTO.setActivityCount(activityCount);
                skuProductResponseDTOS.add(skuProductResponseDTO);
            }
            log.info("查询sku商品集合完成 activityId:{} skuProductResponseDTOS:{}", activityId, JSON.toJSONString(skuProductResponseDTOS));
            return Response.<List<SkuProductResponseDTO>>builder()
                    .code(ResponseCode.SUCCESS.getCode())
                    .info(ResponseCode.SUCCESS.getInfo())
                    .data(skuProductResponseDTOS).build();

        } catch (Exception e) {
            log.error("查询sku商品集合失败 activityId:{}", activityId, e);
            return Response.<List<SkuProductResponseDTO>>builder()
                    .code(ResponseCode.UN_ERROR.getCode())
                    .info(ResponseCode.UN_ERROR.getInfo())
                    .build();
        }
    }

    @Override
    public Response<BigDecimal> queryUserCreditAccount(String userId) {
        try {
            log.info("查询用户积分值开始 userId:{}", userId);
            CreditAccountEntity creditAccountEntity = creditAdjustService.queryUserCreditAccount(userId);
            log.info("查询用户积分值完成 userId:{} adjustAmount:{}", userId, creditAccountEntity.getAdjustAmount());
            return Response.<BigDecimal>builder()
                    .code(ResponseCode.SUCCESS.getCode())
                    .info(ResponseCode.SUCCESS.getInfo())
                    .data(creditAccountEntity.getAdjustAmount())
                    .build();
        } catch (Exception e) {
            return Response.<BigDecimal>builder()
                    .code(ResponseCode.UN_ERROR.getCode())
                    .info(ResponseCode.UN_ERROR.getInfo())
                    .build();
        }
    }

    @Override
    public Response<Boolean> creditPayExchangeSku(SkuProductShopCartRequestDTO shopCartRequestDTO) {
        String userId = shopCartRequestDTO.getUserId();
        Long sku = shopCartRequestDTO.getSku();
        log.info("积分兑换商品，支付订单开始  userId:{} sku:{}", userId, sku);
        try {
            if (StringUtils.isBlank(userId) || sku == null) {
                throw new AppException(ResponseCode.ILLEGAL_PARAMETER.getCode(), ResponseCode.ILLEGAL_PARAMETER.getInfo());
            }
            //1.创建sku订单
            SkuRechargeEntity skuRechargeEntity = new SkuRechargeEntity();
            skuRechargeEntity.setSku(sku);
            skuRechargeEntity.setUserId(userId);
            skuRechargeEntity.setOutBusinessNo(RandomStringUtils.randomAlphanumeric(12));
            skuRechargeEntity.setOrderTradeType(OrderTradeTypeVO.credit_pay_trade);
            UnpaidActivityOrderEntity unpaidActivityOrderEntity = raffleAccountQuotaService.createOrder(skuRechargeEntity);
            //2.创建扣减积分订单
            TradeEntity tradeEntity = new TradeEntity();
            tradeEntity.setUserId(userId);
            tradeEntity.setTradeName(TradeNameVO.CONVERT_SKU);
            tradeEntity.setTradeType(TradeTypeVO.REVERSE);
            tradeEntity.setOutBusinessNo(unpaidActivityOrderEntity.getOutBusinessNo());
            tradeEntity.setAmount(unpaidActivityOrderEntity.getPayAmount());
            String orderId = creditAdjustService.createOrder(tradeEntity);
            log.info("积分兑换商品，支付订单完成  userId:{} sku:{} orderId:{}", userId, sku, orderId);
            //3.返回结果
            return Response.<Boolean>builder()
                    .code(ResponseCode.SUCCESS.getCode())
                    .info(ResponseCode.SUCCESS.getInfo())
                    .data(true).build();
        }catch (Exception e) {
            log.error("积分兑换商品失败 userId:{} sku:{}", userId, sku, e);
            return Response.<Boolean>builder()
                    .code(ResponseCode.UN_ERROR.getCode())
                    .info(ResponseCode.UN_ERROR.getInfo())
                    .data(false).build();
        }
    }

}
